package com.dsl.tms.aspect;

import com.dsl.tms.annotation.LoginRequired;
import com.dsl.tms.entity.result.Result;
import com.dsl.tms.enums.AdminLoginResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class TokenAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    @Pointcut("@annotation(loginRequired)")
    public void loginRequiredMethod(LoginRequired loginRequired){}


    @Around("loginRequiredMethod(loginRequired)")
    public Object addTokenTime(ProceedingJoinPoint joinPoint, LoginRequired loginRequired) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Object obj = null;
        if (!isLoginRequire(method)){
            obj = joinPoint.proceed();
            return obj;
        }
        String[] paramNames = methodSignature.getParameterNames();
        Object[] params = joinPoint.getArgs();
        HashMap keyValues = new HashMap();
        for (int i = 0; i < paramNames.length; i++){
            keyValues.put(paramNames[i],params[i]);
        }
        String token = (String) keyValues.get("token");
        if (!isLogin(token)){
            Class clazz = methodSignature.getReturnType();
            Result result = new Result();
            if (clazz.getName().equals("java.util.HashMap")){ //如果返回类型是HashMap
                obj = new HashMap<String,Object>();
                result.setCode(AdminLoginResult.NERVER_LOGIN.getCode());
                result.setDescription(AdminLoginResult.NERVER_LOGIN.getDescription());
                ((HashMap) obj).put("result",result);
            }else {
                obj = clazz.newInstance();
                //Method put = clazz.getMethod("put", new Class[] {String.class,Result.class}); 多参数时
                Method setResult = clazz.getMethod("setResult",Result.class);
                AdminLoginResult adminLoginResult = AdminLoginResult.NERVER_LOGIN;
                result.setCode(adminLoginResult.getCode());
                result.setDescription(adminLoginResult.getDescription());
                setResult.invoke(obj,result);
            }
            return obj;
        }
        redisTemplate.expire(token,3600,TimeUnit.SECONDS);
        obj = joinPoint.proceed();
        return obj;
    }

    private boolean isLogin(String token){
        Long expireTime = redisTemplate.getExpire(token);
        if (expireTime < 0){
            return false;
        }
        return true;
    }

    private boolean isLoginRequire(Method method){
        boolean result = false;
        if (method.isAnnotationPresent(LoginRequired.class)){
            result = method.getAnnotation(LoginRequired.class).loginRequired();
        }
        return result;
    }

}
